import json
import re
import pymysql
import datetime
import pandas as pd
import templates


com_json=templates.DATA_JSON()
db_iotdb=templates.DB_IOTDB()
db_mysql=templates.DB_MYSQL()


class OPEN_IOTDB:
    # 6个字段存入IOTDB
    def six_json(self,dir,goal):
        json_list=['activity','change_requests','code_change_lines_add','issue_comments','new_contributors','participants']

        for i in range(len(json_list)):
            # 读取 JSON 数据
            with open(f'{goal}/{json_list[i]}.json', 'r') as f:
                data = json.load(f)
            # 筛选并格式化日期键，将非年月的数据清除
            final_data = {
                f"{key}-01 00:00:00" if re.match(r'^\d{4}-\d{2}$', key) else key: value
                for key, value in data.items() if re.match(r'^\d{4}-\d{2}$', key)
            }

            # 将现有数据的日期转为 Datetime 格式
            existing_dates = pd.to_datetime(list(final_data.keys()))
            # 获取列表第一个月份和最后一个月份中间的所有月份
            full_date_range = pd.date_range(start=existing_dates[0], end=existing_dates[-1], freq='MS')

            # 找出缺失的日期
            missing_dates = [date for date in full_date_range if date not in existing_dates]
            print(f"{json_list[i]}缺失的日期:", len(missing_dates))

            # 将缺失的日期加入到 final_data 中
            for date in missing_dates:
                final_data[str(date)] = 0.0

            # 按日期排序 字典
            final_data = dict(sorted(final_data.items()))

            # 将字典转换为列表，列表中的每一项是一个字典，包含 "timestamp" 和 "temperature"
            seq_of_parameters = [
                {"timestamp": datetime.datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S"), "values": temperature}
                for timestamp, temperature in final_data.items()
            ]

            # 创建时间序列(字段)
            db_iotdb.cursor.execute(f"create timeseries root.opendigger.{dir}.{json_list[i]} double")

            # 插入数据sql
            sql = f"insert into root.opendigger.{dir}(timestamp,{json_list[i]}) values(%(timestamp)s,%(values)s)"

            # 使用executemany方法批量插入数据
            db_iotdb.cursor.executemany(sql, seq_of_parameters)

    def insert_data(self):

        db_iotdb.iotdb()
        db_iotdb.cursor = db_iotdb.conn.cursor()

        for i in range(100):
            # 获取项目名和项目相对地址
            table,goal=com_json.dir_json(i)
            self.six_json(table,goal)
            print('------------------------------------------')

        db_iotdb.cursor.close()
        db_iotdb.conn.close()

class OPEN_MYSQL:
    # 将缺失的月份补齐
    def lack_date(self,json_list,final_data):
        # 将现有数据的日期转为 Datetime 格式
        existing_dates = pd.to_datetime(list(final_data.keys()))

        full_date_range = pd.date_range(start=existing_dates[0], end=existing_dates[-1], freq='MS')

        # 找出缺失的日期
        missing_dates = [date for date in full_date_range if date not in existing_dates]
        print(f"{json_list}缺失的日期mysql:", len(missing_dates))

        # 将缺失的日期加入到 final_data 中
        for date in missing_dates:
            final_data[str(date)] = '0'

        # 按日期排序字典
        data = dict(sorted(final_data.items()))

        return data

    # 执行sql
    def list_sql(self,sql,combined_list):
        try:
            # 执行sql命令
            db_mysql.cursor.executemany(sql, combined_list)
        except Exception as e:
            print(e)
        finally:
            # 提交
            db_mysql.con.commit()

    # pr响应时间
    def ir_time(self,table,goal):
        json_list = ['issue_response_time']
        with open(f'{goal}/{json_list[0]}.json', 'r') as f:
            data = json.load(f)

        final_data = data["avg"]
        # 补齐缺失月份
        data=self.lack_date(json_list[0],final_data)
        # 将月份和对应响应时间分别形成列表
        year_month, response_time = list(data.keys()), list(data.values())

        # 定义一个函数来处理不同格式的日期字符串
        def parse_timestamp(date_str):
            # 如果日期字符串包含时间部分，则使用该格式
            try:
                return datetime.datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
            # 否则假设日期是年月格式，需要补充日部分
            except ValueError:
                return datetime.datetime.strptime(date_str + "-01", "%Y-%m-%d")

        # 使用列表推导式来处理year_month字典中的键
        timestamps = [parse_timestamp(date) for date in year_month]


        # 创建 item
        item = [table] * len(response_time)
        # 将3个列表合成一个
        combined_list = [
            (i, k, l)  # 这里的 i,k, l分别代表对应的 item, timestamps, response_time
            for i, k, l in zip(item, timestamps, response_time)
        ]

        sql = "INSERT IGNORE INTO ir_times (item,`year_month`, response_time) VALUES (%s, %s,%s)"
        self.list_sql(sql, combined_list)

    # 开发者每月活跃度（项目开发者活跃度比例），每人每月的巴士系数（核心贡献者总人数）
    def ac_bus(self,table,goal):
        json_list = ['activity_details', 'bus_factor_detail']
        for i in range(len(json_list)):
            # 读取 JSON 数据
            with open(f'{goal}/{json_list[i]}.json', 'r') as f:
                data = json.load(f)
            # 筛选并格式化日期键
            final_data = {
                f"{key}-01 00:00:00" if re.match(r'^\d{4}-\d{2}$', key) else key: value
                for key, value in data.items() if re.match(r'^\d{4}-\d{2}$', key)
            }
            # 补齐缺失月份
            data=self.lack_date(json_list[i],final_data)

            # 遍历 data 字典
            for date_str, value in data.items():
                # 转换后的数据
                converted_data = []
                # 将日期字符串转换为 datetime 对象
                timestamp = datetime.datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")

                if isinstance(value, list):  # 判断 value 是否是一个列表
                    for name, score in value:
                        # 添加转换后的数据
                        converted_data.append({
                            'timestamp': timestamp,
                            'name': name,
                            'values': score
                        })
                elif isinstance(value, (int, float)):  # 当 value不是列表，而是一个单一的数值时，执行
                    converted_data.append({
                        'timestamp': timestamp,
                        'name': '0',
                        'values': value
                    })

                if not len(converted_data):
                    continue

                # 提取 timestamp, name 和 values
                timestamps, names, values = zip(
                    *[(entry['timestamp'], entry['name'], entry['values']) for entry in converted_data])

                # item，table_json列表
                item = [table] * len(data)
                table_json = [json_list[i]] * len(data)
                # 将5个列表合成一个
                combined_list = [
                    (i, j, k, l, m)  # 这里的 i, j, k, l, m 分别代表对应的 item, table_json, timestamp, name 和 values
                    for i, j, k, l, m in zip(item, table_json, timestamps, names, values)
                ]

                sql = "INSERT IGNORE INTO users_month (item,table_json,times,contributor,value_number) VALUES " \
                      "(%s, %s,%s, %s,%s)"

                self.list_sql(sql,combined_list)

    # 项目每月新增贡献者名单
    def new_contributors(self,table,goal):
        json_list = ['new_contributors_detail']
        with open(f'{goal}/{json_list[0]}.json', 'r') as f:
            final_data = json.load(f)

        data=self.lack_date(json_list[0],final_data)

        # 结果列表
        result = []

        # 遍历字典
        for date_str, names in data.items():
            # 处理日期字符串，转换为 datetime 对象
            timestamp = datetime.datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S') if ' ' in date_str else \
                datetime.datetime.strptime(date_str, '%Y-%m')
            for name in names:
                result.append({'timestamp': timestamp, 'name': name})

        timestamps, names = zip(*[(entry['timestamp'], entry['name']) for entry in result])

        # 创建 item 列表
        item = [table] * len(timestamps)
        # 将3个列表合成一个
        combined_list = [
            (i, j, k)  # 这里的 i, j, k 分别代表对应的 item,year_month,contributor
            for i, j, k in zip(item, timestamps, names)
        ]
        sql = "INSERT IGNORE INTO new_contributors (item,`year_month`,contributor) VALUES (%s, %s,%s)"

        self.list_sql(sql, combined_list)


    def insert_data(self):

        db_mysql.Connect()
        db_mysql.cursor = db_mysql.con.cursor()

        for i in range(100):
            table, goal = com_json.dir_json(i)
            print(table, goal)
            self.ir_time(table,goal)
            self.ac_bus(table,goal)
            self.new_contributors(table, goal)
            print('------------------------------------------')

        db_mysql.cursor.close()
        db_mysql.con.close()

# IOTDB插入数据
model=OPEN_IOTDB()
model.insert_data()

# MYSQL插入数据
open_sql=OPEN_MYSQL()
open_sql.insert_data()

